package com.zx.framework.core.util;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.FatalBeanException;
import org.springframework.util.Assert;


public class BeanUtil extends BeanUtils {
	private static final Logger LOGGER = Logger
			.getLogger(BeanUtil.class);
	/**
	 * 将source不为null的内容扩展到target<br>
	 * 如果属性在source中为null,则使用target的值
	 * @author wangguowei
	 * 
	 * @param source
	 * @param target
	 */
	public static void extend(Object source, Object target,String... ignoreProperties){
		Assert.notNull(source, "Source must not be null");
		Assert.notNull(target, "Target must not be null");
		
		PropertyDescriptor[] sourcePds = getPropertyDescriptors(source.getClass());
		List<String> ignoreList = (ignoreProperties != null) ? Arrays.asList(ignoreProperties) : null;
		for(PropertyDescriptor sourcePd:sourcePds){
			Method readMethod = sourcePd.getReadMethod();
			if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
				readMethod.setAccessible(true);
			}
			try {
				Object value = readMethod.invoke(source);
				if(value!=null){
					PropertyDescriptor targetPd = getPropertyDescriptor(source.getClass(), sourcePd.getName());
					if (targetPd.getWriteMethod() != null && (ignoreProperties == null || (!ignoreList.contains(targetPd.getName())))) {
						Method writeMethod = targetPd.getWriteMethod();
						if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
							writeMethod.setAccessible(true);
						}
						writeMethod.invoke(target, value);
					}
				}
			} catch (Throwable e) {
				e.printStackTrace();
				throw new FatalBeanException("Could not copy properties from source to target", e);
			}
		}
	}
}
